/*============================================================================
  File:      IDMAlgorithmMetadata.StaticStubs.cpp
 
  Summary:   Static IDMAlgorithmMetadata implementation to paste into implementation file
			 for class implementing the new alg3orithm

  Date:		 September 12, 2003
------------------------------------------------------------------------------
  This file is part of the Microsoft SQL Server Code Samples.
 
  Copyright (C) 2003 Microsoft Corporation.  All rights reserved.
 
This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.
 
THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
============================================================================*/


// IDMAlgorithmMetadata : (static) function implementation

/*static*/ HRESULT  YOUR_ALG_CLASS::GetServiceType(
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ ULONG *out_pServiceTypeID)
{
	// Populate out_pServiceTypeID with a bitfield that describes the
	// mining service types. 
	//
	// The flags are defined in "oledbdm.h": OR together the 
	// appropriate combination.
	
	// DM_SERVICETYPE_CLASSIFICATION	
	// DM_SERVICETYPE_CLUSTERING	
	// DM_SERVICETYPE_ASSOCIATION	
	// DM_SERVICETYPE_DENSITY_ESTIMATE
	// DM_SERVICETYPE_SEQUENCE	
    
	*out_pServiceTypeID	= 0;
	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetServiceName( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ DMString *io_pstrServiceName)
{
	// MINING_SERVICES Schema Rowset column: SERVICE_NAME
	//
	// The name of the algorithm. Provider-specific. This will 
	// be used as the service identifier in the language. 
	// (It is not localizable.)
	//
	// The name must be a valid XML element name, which means it 
	// is restricted to one "word" and cannot contain any special
	// characters.
    
	static const LPWSTR szName	=	L"SERVICENAME";

	// Use the string handling from IDMContextServices to copy
	// your algorithm name to io_pstrServiceName;
	CComPtr<IDMStringHandler> spidmstringhandler;
	HRESULT hr	= in_pContext->GetStringHandler(&spidmstringhandler);
	RETURN_ON_FAIL(hr);

	return spidmstringhandler->CopyBufferToHandle(io_pstrServiceName, 
											      szName, 
											      (UINT) wcslen(szName));
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetDisplayName( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ DMString *io_pstrDisplayName)
{
	// MINING_SERVICES Schema Rowset column: SERVICE_DISPLAY_NAME 
	
	// The localizable display name of the algorithm.

	// ToDo: change -1 to the resource ID for the string containing the 
	// display name

	static const int	iIDStrAlgorithm = -1;	// Resource ID for the string containing the
												// display name
	static const int	cchMaxDisplay	= 2000;
	WCHAR	szDisplay[cchMaxDisplay + 1];

	// Get the locale from the context-services interface 
	LCID lcid;
	HRESULT hr = in_pContext->GetContextLocaleID(&lcid);
	RETURN_ON_FAIL(hr);

	// Get the display name using the resource ID and locale
	hr = ::LoadStringFromID(iIDStrAlgorithm, lcid, szDisplay, cchMaxDisplay);
	RETURN_ON_FAIL(hr);

	// Grab a string handler to copy szDisplay to the output
	CComPtr<IDMStringHandler> spidmstringhandler;	// Smart pointer for a string handler
	hr	= in_pContext->GetStringHandler(&spidmstringhandler);
	RETURN_ON_FAIL(hr);
	return spidmstringhandler->CopyBufferToHandle(io_pstrDisplayName, 
												  szDisplay, 
												  (UINT)wcslen(szDisplay));
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetServiceGuid( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ GUID *out_pguidServiceGUID)
{
	// GUID that uniquely identifies the algorithm. 
	//*out_pguidServiceGUID = CLSID_ALGORITHM;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetDescription( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ DMString *io_pstrDescription)
{
	// MINING_SERVICES Schema Rowset column: DESCRIPTION
	
	// Human-readable description of the algorithm.

	// ToDo: change -1 to the resource ID for the string containing the 
	// algorithm description

	static const int	iIDStrDescription = -1;		// Resource ID for the string containing the
													// algorithm's description
	static const int	cchMaxDescription = 2000;
	WCHAR	szDescription[cchMaxDescription + 1];

	// Get the locale from the context-services interface 
	LCID lcid;
	HRESULT hr = in_pContext->GetContextLocaleID(&lcid);
	RETURN_ON_FAIL(hr);

	// Get the description using the resource ID and locale
	hr = ::LoadStringFromID(iIDStrDescription, lcid, szDescription, cchMaxDescription);
	RETURN_ON_FAIL(hr);

	// Grab a string handler to copy szDescription to the output
	CComPtr<IDMStringHandler> spidmstringhandler;	// Smart pointer for a string handler
	hr	= in_pContext->GetStringHandler(&spidmstringhandler);
	RETURN_ON_FAIL(hr);
	return spidmstringhandler->CopyBufferToHandle(io_pstrDescription, 
												  szDescription, 
												  (UINT)wcslen(szDescription));
}


/*static*/ HRESULT  YOUR_ALG_CLASS::GetPredictionLimit(
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ LONG *out_pPredictionLimit)
{
	// MINING_SERVICES Schema Rowset column: PREDICTION_LIMIT
	//
	// The maximum number of predictions the model and algorithm 
	// can provide; 0 means no limit. In most cases, this should
	// be no limit.

	*out_pPredictionLimit = 0;
	
	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetSupDistributionFlags( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ ULONG **out_prgFlags,
    /* [out] */ ULONG *out_cFlags)
{
	// MINING_SERVICES Schema Rowset column: SUPPORTED_DISTRIBUTION_FLAGS

	*out_prgFlags = NULL;
	*out_cFlags	  =	0;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetSupInputContentTypes( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ ULONG **out_prgTypes,
    /* [out] */ ULONG *out_cTypes)
{
	// MINING_SERVICES Schema Rowset column: SUPPORTED_INPUT_CONTENT_TYPES 

	// An array of one or more of the allowed column-content types for the
	// input variables. You should always include
	//
	//		DM_MININGCOLUMN_CONTENT_KEY
	//
	// as a supported "input content", even though the Key is typically not
	// an input variable; in this context, "input" means "not output".
	//
	// Simply un-comment the other ones that are appropriate to your algorithm.

	static ULONG	rgminingmodelcontentInputTypes[] = 
	{		
		(ULONG) DM_MININGCOLUMN_CONTENT_KEY,
	//  (ULONG) DM_MININGCOLUMN_CONTENT_DISCRETE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_CONTINUOUS,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_DISCRETIZED,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_SEQUENCETIME,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_ORDERED,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_CYCLICAL,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_NESTEDTABLE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_KEY_SEQUENCE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_KEY_TIME,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_PROBABILITY,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_VARIANCE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_STDDEV,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_SUPPORT,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_PROBABILITYVARIANCE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_PROBABILITYSTDDEV
	};

	static const ULONG cminingmodelcontentInputTypes = 
		sizeof(rgminingmodelcontentInputTypes)/sizeof(ULONG);
	
	*out_prgTypes	= rgminingmodelcontentInputTypes;
	*out_cTypes		= cminingmodelcontentInputTypes;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetSupPredictContentTypes( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ ULONG **out_prgTypes,
    /* [out] */ ULONG *out_cTypes)
{
	// MINING_SERVICES Schema Rowset column: SUPPORTED_PREDICTION_CONTENT_TYPES 

	// Same as above but for the output variable(s) - in this case you only 
	// want to include DM_MININGCOLUMN_CONTENT_KEY if your model uses the Key
	// as an output variable, which is not often the case. The 
	// DM_MININGCOLUMN_CONTENT_DISCRETE option is not commented below simply
	// so that this file will compile with minimal modification; only leave
	// this uncommented if your model supports discrete-variable outputs.

	static ULONG	rgminingmodelcontentOutputTypes[] = 
	{		
		(ULONG) DM_MININGCOLUMN_CONTENT_DISCRETE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_CONTINUOUS,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_DISCRETIZED,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_SEQUENCETIME,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_ORDERED,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_CYCLICAL,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_NESTEDTABLE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_KEY,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_KEY_SEQUENCE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_KEY_TIME,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_PROBABILITY,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_VARIANCE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_STDDEV,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_SUPPORT,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_PROBABILITYVARIANCE,
	//	(ULONG) DM_MININGCOLUMN_CONTENT_PROBABILITYSTDDEV
	};

	static const ULONG cminingmodelcontentOutputTypes = 
		sizeof(rgminingmodelcontentOutputTypes)/sizeof(ULONG);
	
	*out_prgTypes	= rgminingmodelcontentOutputTypes;
	*out_cTypes		= cminingmodelcontentOutputTypes;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetSupModelingFlags( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ DM_MODELING_FLAG **out_prgFlags,
    /* [out] */ ULONG *out_pcFlags)
{
	// MINING_SERVICES Schema Rowset column: SUPPORTED_MODELING_FLAGS 
	
	*out_prgFlags = NULL;
	*out_pcFlags = 0;
	
	return S_OK;
}


/*static*/ HRESULT  YOUR_ALG_CLASS::GetModelingFlagName( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in]  */ DM_MODELING_FLAG in_Flag,
    /* [out] */ DMString *io_pstrFlagName)
{
	// Return the name of the flag.
	io_pstrFlagName = NULL;

	return S_OK;
}


/*static*/ HRESULT  YOUR_ALG_CLASS::GetTrainingComplexity( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ LONG *out_pTrainingComplexity)
{
	// MINING_SERVICES Schema Rowset column: TRAINING_COMPLEXITY

	// Indication of expected time for training:
	//
	// DM_TRAINING_COMPLEXITY_LOW : 
	// Running time is proportional to input and is relatively short.
	//
	// DM_TRAINING_COMPLEXITY_MEDIUM : 
	// Running time may be long but is generally proportional to input. 
	//
    // DM_TRAINING_COMPLEXITY_HIGH : 
	// Running time is long and may grow exponentially in relationship to input.

	//	*out_pTrainingComplexity = DM_TRAINING_COMPLEXITY_XXXX;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetPredictionComplexity( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ LONG *out_pPredictionComplexity)
{
	// MINING_SERVICES Schema Rowset column: PREDICTION_COMPLEXITY

	// Indication of expected time for prediction:
	//
	// DM_PREDICTION_COMPLEXITY_LOW : 
	// Running time is proportional to input and is relatively short.
	// 
	// DM_PREDICTION_COMPLEXITY_MEDIUM : 
	// Running time may be long but is generally proportional to input. 
	//
	// DM_ PREDICTION_COMPLEXITY_HIGH : 
	// Running time is long and may grow exponentially in relationship to input.

	// *out_pPredictionComplexity = DM_PREDICTION_COMPLEXITY_XXXX;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetExpectedQuality( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ LONG *out_pExpectedQuality)
{
	// MINING_SERVICES Schema Rowset column: EXPECTED_QUALITY

	// You need not set this
	// parameter.

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetScaling( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ LONG *out_pScaling)
{
	// MINING_SERVICES Schema Rowset column: SCALING
	
	// You need not set this
	// parameter.

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetAllowIncrementalInsert( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ BOOL *out_pfIncrementalInsert)
{
	// MINING_SERVICES Schema Rowset column: ALLOW_INCREMENTAL_INSERT

	// Return TRUE if you allow incremental insert. The server does
	// not currently use this feature.

	*out_pfIncrementalInsert = FALSE;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetAllowDuplicateKey( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ BOOL *out_pfDuplicateKey)
{
	// MINING_SERVICES Schema Rowset column: ALLOW_DUPLICATE_KEY

	// True if cases may have duplicate key. The engine
	// does not support this, and thus the value should be false.

	*out_pfDuplicateKey = FALSE;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetControl( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ LONG *out_pControl)
{
	// MINING_SERVICES Schema Rowset column: CONTROL

	// You need not set this
	// parameter.

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetViewerType( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ DMString *io_pstrViewerType)
{
	// Returns the name of the viewer that will be used to view
	// this model. The built-in viewers are

	// DM_VIEWERTYPE_MICROSOFT_TREE                
	// DM_VIEWERTYPE_MICROSOFT_CLUSTER             
	// DM_VIEWERTYPE_MICROSOFT_SEQUENCE_CLUSTER    
	// DM_VIEWERTYPE_MICROSOFT_TIME_SERIES         
	// DM_VIEWERTYPE_MICROSOFT_NAIVEBAYESIAN       
	// DM_VIEWERTYPE_MICROSOFT_ASSOCIATION_RULES   
	// DM_VIEWERTYPE_MICROSOFT_NEURAL_NETWORK      

	// Example of how to specify the decision-tree viewer
	/*
	static const LPWSTR szViewer	=	DM_VIEWERTYPE_MICROSOFT_TREE;

	CComPtr<IDMStringHandler> spidmstringhandler;
	
	HRESULT hr	= in_pContext->GetStringHandler(&spidmstringhandler);

	RETURN_ON_FAIL(hr);

	return spidmstringhandler->CopyBufferToHandle(io_pstrViewerType, 
												  szViewer, 
												  (UINT)wcslen(szViewer));
	*/
	return S_OK;
}


/*static*/ HRESULT  YOUR_ALG_CLASS::GetSupportsDMDimensions( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ BOOL *out_pfSupportsDMDimensions)
{
	// Specifies whether or not the content of the trained model can be organized 
	// as a browsable hierarchy. 

	// If your algorithm does not support DM Dimensions, just populate the output 
	// variable with FALSE and return S_OK

	*out_pfSupportsDMDimensions = FALSE;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetSupportsDrillthrough( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ BOOL *out_pfSupportsDrillthrough,
    /* [out] */ BOOL *out_pfMustIncludeChildren)
{
	// Specifies whether or not the model will retain references to the original cases
	// to be displayed while browsing. If you support drillthrough, the parameter
	// out_pfMustIncludeChildren is FALSE if the cases stored in a navigation node
	// contain the cases corresponding to all descendants of that node. 

	*out_pfSupportsDrillthrough = FALSE;
	*out_pfMustIncludeChildren = TRUE;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetSupportedFunctions( 
        /* [in] */ IDMContextServices *in_pContext,
        /* [out] */ DM_SUPPORTED_FUNCTION **out_prgFuncs,
        /* [out] */ ULONG *out_cFuncs)
{
	// A "well-known function" call during prediction (like select 
	// PredictHistogram) translates to a Predict call with some specific 
	// flags.
	// 
	// Here, the service (i.e. your algorithm) reports which such flag 
	// combinations are supported, and therefore which prediction functions are 
	// supported. This is also used in populating the prediction_scalar_functions 
	// and prediction_table_functions of the MINING_MODELS schema rowset
	//
	// The possible values are given by the DM_SUPPORTED_FUNCTION_ENUM enumeration in 
	// dmalgo.h, and are listed below. You may comment out the functions that
	// you do not support so that an error is returned when someone tries to 
	// call that function with your algorithm. 
	//
	// It is probably easiest to simply leave these all defined as-is, and then
	// return an error on the Predict() call if you get a combination of
	// flags that you do not support.

	static const DM_SUPPORTED_FUNCTION_ENUM	rgdmfuncmap[]	=	
	{
		DMSF_Predict_Scalar,
		DMSF_Predict_Table,
		DMSF_PredictAssociation,
		DMSF_PredictSequence,
		DMSF_PredictTimeSeries,
		DMSF_PredictSupport,
		DMSF_PredictVariance,
		DMSF_PredictStdev,
		DMSF_PredictProbablility,
		DMSF_PredictAdjustedProbability,
		DMSF_Cluster,
		DMSF_ClusterDistance,
		DMSF_ClusterProbability,
		DMSF_PredictHistogram,
		DMSF_ClusterPredictHistogram,
		DMSF_TopCount,
		DMSF_BottomCount,
		DMSF_TopSum,
		DMSF_BottomSum,
		DMSF_TopPercent,
		DMSF_BottomPercent,
		DMSF_RangeMid,
		DMSF_RangeMin,
		DMSF_RangeMax,
		DMSF_PredictNodeId,
		DMSF_IsInNode,
		DMSF_IsDescendent,
		DMSF_DCluster,
		DMSF_DProbability,
		DMSF_DAdjustedProbability,
		DMSF_DStdev,
		DMSF_DSupport,
		DMSF_DVariance,
		DMSF_DNodeId,
		DMSF_DSequence,
		DMSF_DTime,
		DMSF_DDistance,
		DMSF_Lag,
		DMSF_PredictCaseLikelihood
    };

	static const ULONG cdmfuncmap = sizeof(rgdmfuncmap)/sizeof(DM_SUPPORTED_FUNCTION_ENUM);

	*out_prgFuncs	=	(DM_SUPPORTED_FUNCTION*)&rgdmfuncmap;
	*out_cFuncs		=	cdmfuncmap;

	return S_OK;
}

////////
//
// Parameter Functions:
// --------------------
//
// The stubs below assume that you are using the default parameter-handling mechanistm, 
// in which case your algorithm class will contain a static DMHPARAMHANDLER member that 
// does almost all of the work of these functions for you. If you are not using this mechanism,
// simply delete the call to the corresponding DMHPARAMHANDLER function and replace with
// your own implementation.
//
// See DmhParameters.h to see how the default parameter-handling mechanism is used.
//
// 
////////

/*static*/ HRESULT  YOUR_ALG_CLASS::GetNumParameters( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ ULONG *out_pcParameters)
{
	// Tells the caller the number of parameters that can be passed to your
	// algorithm.

	return _dmhparamhandler.GetNumParameters(in_pContext, out_pcParameters);
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterName( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [out] */ DMString *io_pstrParameterName)
{
	return _dmhparamhandler.GetParameterName(in_pContext, in_iParameter, io_pstrParameterName);
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterType( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [out] */ DMString *io_pstrParameterType)
{
	// The type strings should be the same as the enumeration names of DBTYPEENUM (oledb.h)
	// for the scalar numeric types:
	
	/*
	DBTYPE_I2
	DBTYPE_I4
	DBTYPE_R4
	DBTYPE_R8
	DBTYPE_BOOL
	DBTYPE_UI2
	DBTYPE_UI4
	DBTYPE_I8
	DBTYPE_UI8
	*/

	return _dmhparamhandler.GetParameterType(in_pContext, in_iParameter, io_pstrParameterType);
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterIsRequired( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [out] */ BOOL *out_pfIsRequired)
{
	return _dmhparamhandler.GetParameterIsRequired(in_pContext, in_iParameter, out_pfIsRequired);
}


/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterIsExposed( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [out] */ BOOL *out_pfIsExposed)
{
	return _dmhparamhandler.GetParameterIsExposed(in_pContext, in_iParameter, out_pfIsExposed);
}


/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterFlags( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [out] */ ULONG *out_pulParameterFlags)
{
	return _dmhparamhandler.GetParameterFlags(in_pContext, in_iParameter, out_pulParameterFlags);
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterDescription( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [in] */ ULONG in_LocaleID,
    /* [out] */ DMString *io_pstrDescription)
{
	return _dmhparamhandler.GetParameterDescription(in_pContext, in_iParameter, in_LocaleID, io_pstrDescription);
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterDefaultValue( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [out] */ DMString *io_pstrDefaultValue)
{
	return _dmhparamhandler.GetParameterDefaultValue(in_pContext, in_iParameter, io_pstrDefaultValue);
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetParameterValueEnumeration( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [out] */ DMString *io_pstrValueEnumeration)
{
	// This is a user-friendly representation of the valid
	// values for the parameter (i.e. "(0,1]"). 

	return _dmhparamhandler.GetParameterValueEnumeration(in_pContext, in_iParameter, io_pstrValueEnumeration);
}


/*static*/ HRESULT  YOUR_ALG_CLASS::ParseParameterValue( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ ULONG in_iParameter,
    /* [in] */ DMString* in_pstrParameterStrValue,
    /* [in] */ DMVariantPtr io_pParameterMappedValue)
{
	// The default parameter-handling mechanism can convert strings into numeric values. 
	// If you want to handle more complicated parameter values (such as arrays), 
	// check for the HRESULT returned by the AGPARAMHANDLER: it will be S_FALSE if the current
	// parameter was not a simple numeric type.

	HRESULT hr = _dmhparamhandler.ParseParameterValue(in_pContext,
													  in_iParameter,
													  in_pstrParameterStrValue,
													  io_pParameterMappedValue);

	if (hr == S_FALSE)
	{
        // Specialty parsing here if in_iParameter is not numeric
	}

	return hr;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetMarginalRequirements( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [out] */ DMMarginalRequirements *out_pReq)
{
	// This method lets the engine know whether the plug-in algorithm will
	// need any statistics. If the return value is populated with DMMR_NONE, 
	// the IDMMarginalStat* (3rd) parameter of IDMAlgorithm::Initialize will 
	// be NULL.

	// You should populate the out_Req with one (or a bitmask combination) 
	// of the following values

	/*
	DMMR_NONE
	DMMR_INPUT_STATS
	DMMR_OUTPUT_STATS
	DMMR_ALL_STATS  = DMMR_INPUT_STATS | DMMR_OUTPUT_STATS
	*/

	*out_pReq = DMMR_ALL_STATS;

	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::GetCaseIDModelled(
	/* [in] */ IDMContextServices *in_pContext,
	/* [out] */ BOOL *out_pfIsModelled)
{
	// Set to TRUE if your model is treating the case ID as a separate
	// variable.

	*out_pfIsModelled = FALSE;
	return S_OK;
}

/*static*/ HRESULT  YOUR_ALG_CLASS::ValidateAttributeSet( 
	/* [in]  */	IDMContextServices* in_pContext,
    /* [in] */ IDMAttributeSet *in_pAttributeSet)
{
	// Check whether or not the attribute set is appropriate for the
	// learning algorithm.

	return S_OK;
}